/**
 * Copyright (c) 2009 Teoti Graphix, LLC See:
 *     http://tkarchitecture.teotigraphix.org
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Michael Schmalle mschmalle@teotigraphix.com
 */
package test.suite.dxframework.patterns.manager.meta
{

import mx.events.FlexEvent;

import org.flexunit.Assert;
import org.flexunit.async.Async;
import org.fluint.uiImpersonation.UIImpersonator;
import org.teotigraphix.dx.interfaces.IComponentBehavior;
import org.teotigraphix.dx.patterns.manager.BehaviorManager;
import org.teotigraphix.dx.patterns.manager.MetaManager;
import org.teotigraphix.dx.patterns.manager.meta.ClassMetaData;
import org.teotigraphix.dx.patterns.manager.meta.ComponentAliasInfo;
import org.teotigraphix.dx.patterns.manager.meta.ComponentHandlerInfo;
import org.teotigraphix.dx.patterns.manager.meta.ModelAliasInfo;
import org.teotigraphix.dx.patterns.manager.meta.ModelBindingInfo;
import org.teotigraphix.dx.patterns.manager.meta.ModelHandlerInfo;
import org.teotigraphix.dx.patterns.manager.meta.SkinHandlerInfo;
import org.teotigraphix.dx.patterns.manager.meta.SkinPartAliasInfo;
import org.teotigraphix.dx.patterns.manager.meta.SkinPartHandlerInfo;
import org.teotigraphix.dx.patterns.manager.meta.StyleBindingInfo;

import test.suite.dxframework.support.behavior.IconBehavior;
import test.suite.dxframework.support.behavior.IconBehaviorSubclass;
import test.suite.dxframework.support.component.IconButton;
import test.suite.dxframework.support.component.IconButtonSubclass;

/**
 * @author Michael Schmalle
 * @date 08-03-09
 */
public class TC_ClassMetaData
{
	protected var button:IconButton;
	protected var buttonSubclass:IconButtonSubclass;
	protected var behavior:IComponentBehavior;
	
	[Before(ui,async)]
	public function setUp():void
	{
		button = new IconButton();
		behavior = new IconBehavior();
		
		Async.proceedOnEvent(this, button, FlexEvent.CREATION_COMPLETE);
		UIImpersonator.addChild( button );
		
		BehaviorManager.registerBehavior( button, IconBehavior, behavior );
	}
	
	[After]
	public function tearDown():void
	{
		UIImpersonator.removeChild( button );
		button = null;
	}
	
	//----------------------------------
	//  [ComponentAlias]
	//----------------------------------
	
	[Test]
	public function test_call_getComponentAliasByID():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var alias:ComponentAliasInfo = data.getComponentAliasByID("button");
		Assert.assertNotNull( "ComponentAliasInfo is null", alias );
		Assert.assertEquals( "alias.id", "button", alias.id );
		Assert.assertEquals( "alias.type", "mx.controls::Button", alias.type );
	}
	
	[Test]
	public function test_ComponentAlias_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate ComponentAlias", (data.componentAliases.length == 1) );
	}
	
	//----------------------------------
	//  [SkinPartAlias]
	//----------------------------------
	
	[Test]
	public function test_call_getSkinPartAliasInfoByID_required():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var alias:SkinPartAliasInfo = data.getSkinPartAliasInfoByID("iconDisplay");
		Assert.assertNotNull( "SkinPartAliasInfo is null", alias );
		Assert.assertEquals( "alias.id", "iconDisplay", alias.id );
		Assert.assertEquals( "alias.type", "mx.controls::Image", alias.type );
		Assert.assertTrue( "alias.required", alias.required );
	}
	
	[Test]
	public function test_call_getSkinPartAliasInfoByID_nonrequired():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var alias:SkinPartAliasInfo = data.getSkinPartAliasInfoByID("labelDisplay");
		Assert.assertNotNull( "SkinPartAliasInfo is null", alias );
		Assert.assertEquals( "alias.id", "labelDisplay", alias.id );
		Assert.assertEquals( "alias.type", "mx.core::IUITextField", alias.type );
		Assert.assertFalse( "alias.required", alias.required );
	}
	
	[Test]
	public function test_SkinPartAlias_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate SkinPartAlias", (data.skinPartAliases.length == 2) );
	}
	
	//----------------------------------
	//  [ModelAlias]
	//----------------------------------
	
	[Test]
	public function test_call_getModelAliasByID():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var alias:ModelAliasInfo = data.getModelAliasByID("tintModel");
		Assert.assertNotNull( "ModelAliasInfo is null", alias );
		Assert.assertEquals( "alias.id", "tintModel", alias.id );
		Assert.assertEquals( "alias.type", "Object", alias.type );
	}	
	
	[Test]
	public function test_ModelAlias_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate ModelAlias", (data.modelAliases.length == 1) );
	}
	
	//----------------------------------
	//  [ComponentHandler]
	//----------------------------------
	
	[Test]
	public function test_call_getComponentHandlerByEvent():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var handler:ComponentHandlerInfo = data.getComponentHandlerByEvent("iconChanged");
		Assert.assertNotNull( "ComponentHandlerInfo is null", handler );
		Assert.assertTrue( "not class handler", handler.isClassHandler() );
		// deprecated
		Assert.assertEquals( "alias.dispatcher", "component", handler.dispatcher );
		Assert.assertEquals( "alias.event", "iconChanged", handler.event );
		Assert.assertEquals( "alias.handler", "iconHandler", handler.handler );
		Assert.assertEquals( "alias.phase", "capture", handler.phase );
		Assert.assertEquals( "alias.priority", 10, handler.priority );
		Assert.assertTrue( "alias.weak", handler.weak );
	}
	
	[Test]
	public function test_ComponentHandler_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate ComponentHandler", (data.componentHandlers.length == 1) );
	}
	
	//----------------------------------
	//  [SkinHandler]
	//----------------------------------
	
	[Test]
	public function test_call_getSkinHandlerByEvent():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var handler:SkinHandlerInfo = data.getSkinHandlerByEvent("click");
		Assert.assertNotNull( "SkinHandlerInfo is null", handler );
		Assert.assertTrue( "not class handler", handler.isClassHandler() );
		// deprecated
		Assert.assertEquals( "alias.dispatcher", "component.skin", handler.dispatcher );
		Assert.assertEquals( "alias.event", "click", handler.event );
		Assert.assertEquals( "alias.handler", "clickHandler", handler.handler );
		Assert.assertEquals( "alias.phase", "both", handler.phase );
		Assert.assertEquals( "alias.priority", 20, handler.priority );
		Assert.assertFalse( "alias.weak", handler.weak );
	}
	
	[Test]
	public function test_SkinHandler_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate SkinHandler", (data.skinHandlers.length == 1) );
	}
	
	//----------------------------------
	//  [SkinPartHandler]
	//----------------------------------
	
	[Test]
	public function test_call_member_getSkinPartHandlerInfoByEvent():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var handler:SkinPartHandlerInfo = data.getSkinPartHandlerInfoByEvent("enabledChanged");
		Assert.assertNotNull( "SkinPartHandlerInfo is null", handler );
		Assert.assertFalse( "is class handler", handler.isClassHandler() );
		// deprecated
		Assert.assertEquals( "alias.dispatcher", "labelDisplay", handler.dispatcher );
		Assert.assertEquals( "alias.event", "enabledChanged", handler.event );
		Assert.assertEquals( "alias.handler", "labelDisplay_enabledHandler", handler.handler );
		Assert.assertEquals( "alias.phase", "bubble", handler.phase );
		Assert.assertEquals( "alias.priority", 30, handler.priority );
		Assert.assertTrue( "alias.weak", handler.weak );
	}
	
	[Test]
	public function test_SkinPartHandler_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate SkinPartHandler", (data.skinPartHandlers.length == 2) );
	}
	
	//----------------------------------
	//  [SkinPartHandler]
	//----------------------------------
	
	[Test]
	public function test_call_class_getSkinPartHandlerInfoByEvent():void
	{
		// tests a SkinPartHandler in a subclass's class metadata header
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var handler:SkinPartHandlerInfo = data.getSkinPartHandlerInfoByEvent( "mouseDown");
		
		Assert.assertNotNull( "SkinPartHandlerInfo is null", handler );
		Assert.assertFalse( "is class handler", handler.isClassHandler() );
		
		Assert.assertEquals( "alias.dispatcher", "labelDisplay", handler.dispatcher );
		Assert.assertEquals( "alias.event", "mouseDown", handler.event );
		Assert.assertEquals( "alias.handler", "labelDisplay_mouseDownHandler", handler.handler );
		Assert.assertEquals( "alias.phase", "both", handler.phase );
		Assert.assertEquals( "alias.priority", 20, handler.priority );
		Assert.assertFalse( "alias.weak", handler.weak );		
	}	
	
	//----------------------------------
	//  [StyleBinding]
	//----------------------------------
	
	[Test]
	public function test_call_getStyleBindingByName():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var alias:StyleBindingInfo = data.getStyleBindingByName("iconAlpha");
		Assert.assertNotNull( "StyleBindingInfo is null", alias );
		Assert.assertEquals( "alias.id", "iconAlpha", alias.id );
		Assert.assertEquals( "alias.type", "Number", alias.type );
	}
	
	[Test]
	public function test_StyleBinding_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate StyleBinding", (data.styleBindings.length == 1) );
	}
	
	//----------------------------------
	//  [ModelBinding]
	//----------------------------------
	
	[Test]
	public function test_call_getModelBindingByID():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( button );
		var alias:ModelBindingInfo = data.getModelBindingByID("modelProperty");
		Assert.assertNotNull( "ModelBindingInfo is null", alias );
		Assert.assertEquals( "alias.id", "modelProperty", alias.id );
		Assert.assertEquals( "alias.type", "String", alias.type );
		Assert.assertEquals( "alias.api", "mx.controls.Button", alias.api );
		Assert.assertEquals( "alias.binding", "propertyChange", alias.binding );
		
		alias = data.getModelBindingByID("modelPropertyAPINoArg");
		Assert.assertNotNull( "ModelBindingInfo is null", alias );
		Assert.assertEquals( "alias.id", "modelPropertyAPINoArg", alias.id );
		Assert.assertEquals( "alias.type", "int", alias.type );
		Assert.assertEquals( "alias.api", "mx.controls.Button", alias.api );
		Assert.assertEquals( "alias.binding", "modelPropertyChanged", alias.binding );
	}
	
	[Test]
	public function test_ModelBinding_subclass_duplicates():void
	{
		var bc:IconButtonSubclass = new IconButtonSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate ModelBinding", (data.modelBindings.length == 2) );
	}
	
	//----------------------------------
	//  [ModelHandler]
	//----------------------------------
	
	[Test]
	public function test_call_getModelHandlerByEvent():void
	{
		var data:ClassMetaData = MetaManager.resolveClassMetaData( behavior );
		var handler:ModelHandlerInfo = data.getModelHandlerByEvent("enabledChanged");
		Assert.assertNotNull( "ModelHandlerInfo is null", handler );
		Assert.assertTrue( "not class handler", handler.isClassHandler() );
		// deprecated
		//Assert.assertEquals( "alias.dispatcher", "component.skin", handler.dispatcher );
		Assert.assertEquals( "alias.event", "enabledChanged", handler.event );
		Assert.assertEquals( "alias.handler", "model_enabledHandler", handler.handler );
		Assert.assertEquals( "alias.phase", "bubble", handler.phase );
		Assert.assertEquals( "alias.priority", 30, handler.priority );
		Assert.assertTrue( "alias.weak", handler.weak );
	}
	
	[Test]
	public function test_ModelHandler_subclass_duplicates():void
	{
		var bc:IconBehaviorSubclass = new IconBehaviorSubclass();
		
		var data:ClassMetaData = MetaManager.resolveClassMetaData( bc );
		Assert.assertTrue( "duplicate ModelHandler", (data.modelHandlers.length == 1) );
	}	
}
}